`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/11/12 13:50:23
// Design Name: 
// Module Name: MAC_Process
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module mac_rx_data_process#(
    parameter       TARGET_MAC = 48'hff_ff_ff_ff_ff_ff    ,
                    SOURCE_MAC = 48'h01_02_03_04_05_06    
)(
    input               i_clk                   ,
    input               i_rst                   ,

    input  [47:0]       i_set_target_mac        ,
    input               i_set_target_valid      ,
    input  [47:0]       i_set_source_mac        ,
    input               i_set_source_valid      ,

    output              o_broadcast             ,
    output [7 :0]       o_axis_rx_data          ,
    output [31:0]       o_axis_rx_user          ,//[31:16]-type；[15:0]-len；
    output              o_axis_rx_last          ,
    output              o_axis_rx_valid         ,
    input               i_axis_rx_ready         ,
    output [31:0]       o_crc_result            ,
    output              o_crc_valid             ,

    input  [7 :0]       i_gmii_rxdata           ,
    input               i_gmii_rxvalid 
);

reg  [47:0]             ri_set_target_mac       ;  
reg  [47:0]             ri_set_source_mac       ;  
reg                     ro_broadcast            ;
reg  [7 :0]             ro_axis_rx_data         ;
reg  [31:0]             ro_axis_rx_user         ;
reg                     ro_axis_rx_last         ;
reg                     ro_axis_rx_valid        ;
reg  [7 :0]             ri_GMII_RxData          ;
reg                     ri_GMII_RxValid         ;
reg                     ri_GMII_RxValid_1d      ;
reg  [15:0]             r_cnt                   ;
reg  [15:0]             r_Header_cnt            ;
reg                     r_Header_access         ;
reg  [47:0]             r_device_target_mac     ;
reg  [47:0]             r_device_source_mac     ;
reg  [15:0]             r_deivce_type           ;
reg                     r_crc_valid             ;
reg                     r_crc_rst               ;
reg  [31:0]             r_crc_data[0:3]         ;
reg  [31:0]             ro_crc_result           ;
reg                     ro_crc_valid            ;

wire [31:0]             w_crc_result            ;
wire                    w_RxEnd                 ;
wire                    w_RxStart               ;

assign o_broadcast     = ro_broadcast           ;
assign o_axis_rx_data  = ro_axis_rx_data        ;
assign o_axis_rx_user  = ro_axis_rx_user        ;
assign o_axis_rx_last  = ro_axis_rx_last        ;
assign o_axis_rx_valid = ro_axis_rx_valid       ;

assign w_RxEnd = !ri_GMII_RxValid & ri_GMII_RxValid_1d;
assign w_RxStart = ri_GMII_RxValid & !ri_GMII_RxValid_1d;
assign o_crc_result = ro_crc_result;
assign o_crc_valid  = ro_crc_valid ;

CRC32_D8 CRC32_D8_u0(
    .data_in        (ri_GMII_RxData     ),
    .crc_en         (r_crc_valid        ),
    .crc_out        (w_crc_result       ),
    .rst            (i_rst |r_crc_rst   ),
    .clk            (i_clk              ) 
);

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ri_set_target_mac <= TARGET_MAC;
    else if(i_set_target_valid)
        ri_set_target_mac <= i_set_target_mac;
    else 
        ri_set_target_mac <= ri_set_target_mac;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ri_set_source_mac <= SOURCE_MAC;
    else if(i_set_source_valid)
        ri_set_source_mac <= i_set_source_mac;
    else 
        ri_set_source_mac <= ri_set_source_mac;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        ri_GMII_RxData      <= 'd0;
        ri_GMII_RxValid     <= 'd0;
        ri_GMII_RxValid_1d  <= 'd0;
    end else begin
        ri_GMII_RxData      <= i_gmii_rxdata ;
        ri_GMII_RxValid     <= i_gmii_rxvalid;
        ri_GMII_RxValid_1d  <= ri_GMII_RxValid;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_cnt <= 'd0;
    else if(r_cnt == 6 && ri_GMII_RxData == 16'hD5 && r_Header_cnt >= 5)
        r_cnt <= r_cnt + 'd2;
    else if(ri_GMII_RxValid)
        r_cnt <= r_cnt + 'd1;
    else 
        r_cnt <= 'd0;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_Header_cnt <= 'd0;
    else if(w_RxEnd)
        r_Header_cnt <= 'd0;
    else if(ri_GMII_RxValid && r_cnt <= 6 && ri_GMII_RxData == 16'h55)
        r_Header_cnt <= r_Header_cnt + 1;
    else 
        r_Header_cnt <= r_Header_cnt;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_Header_access <= 'd0;
    else if(w_RxEnd)
        r_Header_access <= 'd0;
    else if(r_cnt == 6 && ri_GMII_RxData == 16'hD5 && r_Header_cnt >= 5)
        r_Header_access <= 'd1;
    else if(r_cnt == 7 && ri_GMII_RxData == 16'hD5 && r_Header_cnt >= 6)
        r_Header_access <= 'd1;
    else 
        r_Header_access <= r_Header_access;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_device_target_mac <= 'd0;
    else if(ri_GMII_RxValid && r_cnt >= 8 && r_cnt <= 13)
        r_device_target_mac <= {r_device_target_mac[39:0],ri_GMII_RxData};
    else 
        r_device_target_mac <= r_device_target_mac;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_device_source_mac <= 'd0;
    else if(ri_GMII_RxValid && r_cnt >= 14 && r_cnt <= 19)
        r_device_source_mac <= {r_device_source_mac[39:0],ri_GMII_RxData};
    else 
        r_device_source_mac <= r_device_source_mac;
end
      
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_deivce_type <= 'd0;
    else if(ri_GMII_RxValid && r_cnt >= 20 && r_cnt <= 21)
        r_deivce_type <= {r_deivce_type[7:0],ri_GMII_RxData};
    else 
        r_deivce_type <= r_deivce_type;
end
    
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        ro_broadcast <= 'd0;
    else if(ri_GMII_RxValid && &r_device_target_mac)
        ro_broadcast <= 'd1;
    else 
        ro_broadcast <= 'd0;
end
 
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        ro_axis_rx_data <= 'd0;
    else 
        ro_axis_rx_data <= ri_GMII_RxData;
end
 
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_axis_rx_user <= 'd0;
    else 
        ro_axis_rx_user <= {r_deivce_type,16'd0};
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_axis_rx_last <= 'd0;
    else if(ro_axis_rx_valid & ro_axis_rx_last)
        ro_axis_rx_last <= 'd0;
    else if(!i_gmii_rxvalid && ri_GMII_RxValid && ro_axis_rx_valid)
        ro_axis_rx_last <= 'd1;
    else 
        ro_axis_rx_last <= ro_axis_rx_last;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        ro_axis_rx_valid <= 'd0;
    else if(ro_axis_rx_valid & ro_axis_rx_last)
        ro_axis_rx_valid <= 'd0;
    // else if(r_cnt == 22 && r_Header_access && (r_device_target_mac == ri_set_source_mac || ro_broadcast))   
    else if(r_cnt == 22 && r_Header_access)
        ro_axis_rx_valid <= 'd1;
    else    
        ro_axis_rx_valid <= ro_axis_rx_valid;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_crc_rst <= 'd0;
    else if(w_RxStart)   
        r_crc_rst <= 'd1;
    else 
        r_crc_rst <= 'd0;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        r_crc_valid <= 'd0;
    else if(!i_gmii_rxvalid && ri_GMII_RxValid && ro_axis_rx_valid)
        r_crc_valid <= 'd0;
    else if(r_cnt == 7)
        r_crc_valid <= 'd1;
    else 
        r_crc_valid <= r_crc_valid;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        r_crc_data[0] <= 'd0;
        r_crc_data[1] <= 'd0;
        r_crc_data[2] <= 'd0;
        r_crc_data[3] <= 'd0;
        ro_crc_result <= 'd0;
        ro_crc_valid  <= 'd0;
    end else begin
        r_crc_data[0] <= w_crc_result;
        r_crc_data[1] <= r_crc_data[0];
        r_crc_data[2] <= r_crc_data[1];
        r_crc_data[3] <= r_crc_data[2];
        ro_crc_result <= r_crc_data[3];
        ro_crc_valid  <= w_RxEnd;
    end
end

endmodule
